import math
from collections import Counter
from urllib.request import urlopen
import csv
import random
import numpy as np

# 加载数据
def load_data(url):
    response = urlopen(url)
    lines = [l.decode('utf-8') for l in response.readlines()]
    cr = csv.reader(lines)
    data = list(cr)
    return data

# 筛选类别标签为 1 和 2 的数据
def filter_data(data):
    filtered_data = [row for row in data if int(row[0]) in [1, 2]]
    labels = [int(row[0]) for row in filtered_data]
    features = [list(map(float, row[1:])) for row in filtered_data]
    return features, labels

# PCA 降维
def pca(data, n_components):
    mean = np.mean(data, axis=0)
    centered_data = data - mean
    cov_matrix = np.cov(centered_data, rowvar=False)
    eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)
    sorted_indices = np.argsort(eigenvalues)[::-1]
    top_eigenvectors = eigenvectors[:, sorted_indices[:n_components]]
    return np.dot(centered_data, top_eigenvectors)

# LDA 降维
def lda(data, labels, n_components):
    unique_labels = np.unique(labels)
    mean_overall = np.mean(data, axis=0)
    S_B = np.zeros((data.shape[1], data.shape[1]))
    S_W = np.zeros((data.shape[1], data.shape[1]))

    for label in unique_labels:
        class_data = data[labels == label]
        mean_class = np.mean(class_data, axis=0)
        S_B += len(class_data) * np.outer(mean_class - mean_overall, mean_class - mean_overall)
        S_W += np.cov(class_data, rowvar=False, bias=True) * (len(class_data) - 1)

    eigenvalues, eigenvectors = np.linalg.eig(np.linalg.inv(S_W).dot(S_B))
    sorted_indices = np.argsort(eigenvalues)[::-1]
    top_eigenvectors = eigenvectors[:, sorted_indices[:n_components]]
    return np.dot(data, top_eigenvectors)

# 主函数
if __name__ == "__main__":
    # 加载数据
    url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data"
    data = load_data(url)

    # 筛选类别标签为 1 和 2 的数据
    features, labels = filter_data(data)
    features = np.array(features)
    labels = np.array(labels)

    # PCA 降维
    pca_features = pca(features, n_components=2)
    print("PCA 降维后的两维特征：")
    print(pca_features)

    # LDA 降维
    lda_features = lda(features, labels, n_components=1)
    print("LDA 降维后的特征：")
    print(lda_features)
